package cz.czu.pef.DataModelling.utils;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import cz.czu.pef.DataModelling.domainObjects.*;
import cz.czu.pef.DataModelling.entityObjects.*;

@Component(value="transformEntityBean")
public class TransformEntityBean {

	@Autowired
	private Mapper dozerMapper;
	private static final Map<Class<?>, Class<?>> mappedClassesMap = new HashMap<Class<?>, Class<?>>();

	private void addMappedClassPair(Class<?> clazz1, Class<?> clazz2)
	{
		mappedClassesMap.put(clazz1, clazz2);
		mappedClassesMap.put(clazz2, clazz1);
	}

	/**
	 * Prepares map of mapped classes (bi-directional)
	 */
	@PostConstruct
	private void prepareMappedClasses()
	{
		addMappedClassPair(Address.class, AddressEntityImpl.class);
		addMappedClassPair(Company.class, CompanyEntityImpl.class);
		addMappedClassPair(Employee.class, EmployeeEntityImpl.class);
		addMappedClassPair(ExternalWorker.class, ExternalWorkerEntityImpl.class);
        addMappedClassPair(Machinery.class, MachineryEntityImpl.class);
        addMappedClassPair(MachineType.class, MachineTypeEntityImpl.class);
        addMappedClassPair(MedicalExamination.class, MedicalExaminationEntityImpl.class);
        addMappedClassPair(MedicalExaminationType.class, MedicalExaminationTypeEntityImpl.class);
        addMappedClassPair(MedicalExaminationTypeForRoleType.class, MedicalExaminationTypeForRoleTypeEntityImpl.class);
        addMappedClassPair(Person.class, PersonEntityImpl.class);
        addMappedClassPair(Role.class, RoleEntityImpl.class);
        addMappedClassPair(RoleType.class, RoleTypeEntityImpl.class);
        addMappedClassPair(Training.class, TrainingEntityImpl.class);
        addMappedClassPair(TrainingType.class, TrainingTypeEntityImpl.class);
        addMappedClassPair(TrainingTypeForRoleType.class, TrainingTypeForRoleTypeEntityImpl.class);
	}

	/**
	 * Transforms fields from one object to another object using Dozer.
	 * Supports complex and nested object field mappings.
	 * 
	 * @param src
	 * @return Destination object
	 */
	public Object transform(final Object src)
	{
		if (src == null)
			throw new IllegalArgumentException("src must not be null");

		Class<?> destClass = mappedClassesMap.get(src.getClass());
		if (destClass == null)
		{
			throw new RuntimeException("Unsupported source Object class: " + src.getClass().getName());
		}

		return dozerMapper.map(src, destClass);
	}
}
